﻿#include <istream>
#include <ostream>
#include <MEMSTORAGE.HPP>
#include <CXXLLIST.HPP>

using namespace CxxlMan;

#define COMPOSITEMEMDATA cxxlComposite<MemData,false>

/*******************************************************************
** 實作 cxxlComposite::Composite_Export()，把子 cxxlComposite 節點
** 中，只存放永續資料的節點和不包含永續資料的子節點(只包含有孫節點)
** 分開，以便 centralizedmgr 的再生功能使用
*******************************************************************/

class IMem_attrComposite_Export
{
public:
    virtual void MemAttrComposite_Export(COMPOSITEMEMDATA *Node) = 0;
};


class Mem_attrComposite:public COMPOSITEMEMDATA
{

  virtual void cxxlFASTCALL Composite_Export(void *def, COMPOSITEMEMDATA *Node) const
  {
    ((IMem_attrComposite_Export *)def)->MemAttrComposite_Export(Node);
  }

  virtual COMPOSITEMEMDATA * cxxlFASTCALL CreateSelf(UNICODE_String idName,ISpirit *spirit) const
  {
    return new Mem_attrComposite(idName,spirit);
  }

public:
  Mem_attrComposite(const UNICODE_String &idName, ISpirit *spirit)
    :cxxlObject(spirit),
    COMPOSITEMEMDATA(idName, spirit)
  {
  }

  virtual ~Mem_attrComposite()
  {
  }
};

class CMem_attrComposite_Export:virtual public cxxlObject, public IMem_attrComposite_Export
{
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > SubNode_List;
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Attr_List;

  virtual void MemAttrComposite_Export(COMPOSITEMEMDATA *Node)
  {
    if(Node->GetName() == SETCOUNT)
      SubNode_List->Push_Front(Node);
    else if(Node->GetObj().isNULL())
      SubNode_List->Push_Front(Node);
    else
      Attr_List->Push_Front(Node);
  }

public:
  CMem_attrComposite_Export()
    :cxxlObject(Spirit_Easy),
    SubNode_List(new cxxlList<COMPOSITEMEMDATA >,this),
     Attr_List(new cxxlList<COMPOSITEMEMDATA >,this)
  {
  }

  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > cxxlFASTCALL GetSubNode_List()
  {
    return SubNode_List;
  }

  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > cxxlFASTCALL GetAttr_List()
  {
    return Attr_List;
  }
};


/********************************
**  class MemSaveFilter
********************************/

/*
** 負責將被儲存體(cxxlPreserve)要保存的資料存起來
*/
class MemSaveFilter:public SaveFilter
{
  COMPOSITEMEMDATA *m_pMemDataComposite;
  Smart_Ptr<cxxlList<MemSaveFilter> > SubSaveFilter_List; // 記錄要可被 toSave() 叫用的子 MemSaveFilter

  cxxlPreserve *_pPreserve;

  // 繼承自 class Filter
  virtual bool cxxlFASTCALL Ref(const bool *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const char *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const short *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const int *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const long *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const wchar_t *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned char *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned short *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned int *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const unsigned long *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const float *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }
  virtual bool cxxlFASTCALL Ref(const double *Src, size_t Count, const UNICODE_String &Name)
  {
    MemData *t_MemData = new MemData(sizeof(*Src) * Count, Src, GetSpirit());
    m_pMemDataComposite->Add(t_MemData,Name);
    return true;
  }

public:
  // Constructor
  MemSaveFilter(
    COMPOSITEMEMDATA *pMemDataComposite,
    cxxlPreserve *pPreserve,
    ISpirit *spirit )
    :cxxlObject(spirit),
    SaveFilter(spirit),SubSaveFilter_List(new cxxlList<MemSaveFilter>(spirit),this)
  {
    _pPreserve = pPreserve;

    if(pPreserve == NULL)
      return;

    Lock(pPreserve);
    m_pMemDataComposite = pMemDataComposite;

    if(GetTransaction(pPreserve) == 0)
    {
      SetTransaction(pPreserve,1);

      for(const _Sets *p = Get_Sets_List(pPreserve);
          p != NULL;
          p = Next_Sets(p))
      {
        Smart_Ptr<cxxlList<cxxlPreserve> > cxxlPreserve_List = GetPreserveList(p);

        unsigned long SubPreserveCount = cxxlPreserve_List->GetCount();

        MemData *t_MemData = new MemData(sizeof(SubPreserveCount), &SubPreserveCount, GetSpirit());
        m_pMemDataComposite->Add(t_MemData,SETCOUNT);

        if(SubPreserveCount == 0)
          continue;

        cxxlPreserve_List->ResetPT(toHead);
        unsigned long i = 0;
        for(Smart_Ptr<cxxlPreserve> cxxlPreserve_Ptr = (*cxxlPreserve_List)++; i < SubPreserveCount; cxxlPreserve_Ptr = (*cxxlPreserve_List)++, ++i)
        {
          MemSaveFilter *SF = new MemSaveFilter(pMemDataComposite->Add(NULL,GetName(p)), cxxlPreserve_Ptr, spirit);
          SubSaveFilter_List->Push_Back(SF);
        }
      }
    }
  }

  // Destructor
  virtual ~MemSaveFilter()
  {
    if(_pPreserve != NULL)
    {
      SetTransaction(_pPreserve,0);
      SaveFilter::UnLock(_pPreserve);
    }
  }

  bool cxxlFASTCALL toSave()
  {
    if(_pPreserve == NULL)
      return true;

    if(GetTransaction(_pPreserve) == 1)
    {
      SaveFilter::SetTransaction(_pPreserve,0); // 同一個 Preserve 不會再被做一次

      // Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > SubMemDataComposite_List = m_pMemDataComposite->cxxlList_Create();
      SubSaveFilter_List->ResetPT(CxxlMan::toHead);
      for(Smart_Ptr<MemSaveFilter> SubSaveFilter_Ptr = (*SubSaveFilter_List)++;
          !SubSaveFilter_Ptr.isNULL();
          SubSaveFilter_Ptr = (*SubSaveFilter_List)++)
      {
        if(!SubSaveFilter_Ptr->toSave())
          return false;
      }
    }

    if(SaveFilter::Save(_pPreserve))
      return true;
	  else
      return false;

  }

};



/********************************
**  class MemLoadFilter
********************************/

/*
** 負責取回被儲存體(cxxlPreserve)保存的資料
*/
class MemLoadFilter:public CxxlMan::LoadFilter
{
protected:
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > SubMemDataComposite_List;

  bool isCommit;

private:
  template<typename T>
  bool cxxlFASTCALL _Load(T *v, size_t Count,const UNICODE_String &Name)
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubMemDataComposite_Ptr = (*SubMemDataComposite_List)++;

    if(!SubMemDataComposite_Ptr.isNULL() && (isCommit || SubMemDataComposite_Ptr->GetName() == Name))
    {
      unsigned long DataLen;
      char *Data;

      Smart_Ptr<MemData> MemData_Ptr = SubMemDataComposite_Ptr->GetObj();
      Data = (char *) MemData_Ptr->Get(DataLen);

      if(isCommit)
      {
        char *Dest = (char*)v;
        for(unsigned int i = 0; i < DataLen; ++i,++Data,++Dest)
          *Dest = *Data;
      }
      else
      {
        if(//DataLen != 0 &&// 儲存的永續資料設為 0 可無修件過關
           Count != DataLen / sizeof(*v))
          return false;
      }
      return true;
    }
    else
      return false;
  }

  // 繼承自 class Filter
  virtual bool cxxlFASTCALL Ref(const bool *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((bool *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const char *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((char *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const short *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((short *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const int *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((int *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const long *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((long *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const wchar_t *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((wchar_t *)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned char *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned char*)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned short *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned short*)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned int *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned int*)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const unsigned long *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((unsigned long*)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const float *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((float*)v, Count, Name);
  }
  virtual bool cxxlFASTCALL Ref(const double *v, size_t Count,const UNICODE_String &Name)
  {
    return _Load((double*)v, Count, Name);
  }


  template<typename T>
  bool cxxlFASTCALL _LoadChk(T **v, size_t *Count,const UNICODE_String &Name)
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubMemDataComposite_Ptr = (*SubMemDataComposite_List)++;

    if(!SubMemDataComposite_Ptr.isNULL() && SubMemDataComposite_Ptr->GetName() == Name)
    {
      unsigned long DataLen;

      Smart_Ptr<MemData> MemData_Ptr = SubMemDataComposite_Ptr->GetObj();
      *v = (T *) MemData_Ptr->Get(DataLen);
      *Count = DataLen / sizeof(**v);
      return true;
    }
    else
      return false;
  }


  // 繼承自 class LoadFilter
  virtual bool cxxlFASTCALL LoadChk(const bool **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const char **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const short **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const int **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const long **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const wchar_t **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned char **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned short **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned int **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const unsigned long **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const float **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }
  virtual bool cxxlFASTCALL LoadChk(const double **v, size_t *Count,const UNICODE_String &Name)
  {
    return _LoadChk(v, Count, Name);
  }

  template<typename T>
  bool cxxlFASTCALL _LoadRef(T **v, const UNICODE_String &Name)
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubMemDataComposite_Ptr = (*SubMemDataComposite_List)++;

    if(!SubMemDataComposite_Ptr.isNULL() && (isCommit || SubMemDataComposite_Ptr->GetName() == Name))
    {
      unsigned long DataLen;
      char *Data;

      Smart_Ptr<MemData> MemData_Ptr = SubMemDataComposite_Ptr->GetObj();
      Data = (char *) MemData_Ptr->Get(DataLen);

      if(isCommit)
      {
        delete [] *v;
        *v = (T*)new char[DataLen];
        char *Dest = (char*)*v;
        for(unsigned int i = 0; i < DataLen; ++i,++Data,++Dest)
          *Dest = *Data;
      }

      return true;
    }
    else
      return false;
  }


  // 繼承自 class LoadFilter
  virtual bool cxxlFASTCALL LoadRef(const bool **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const char **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const short **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const int **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const long **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const wchar_t **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned char **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned short **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned int **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const unsigned long **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const float **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }
  virtual bool cxxlFASTCALL LoadRef(const double **v, const UNICODE_String &Name)
  {
    return _LoadRef(v, Name);
  }

  virtual bool isChk() const
  {
    return isCommit != true;
  }


public:

  // Constructor
  MemLoadFilter(
    const Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > &SubMemDataComposite_Arg,
    ISpirit *spirit )
    :cxxlObject(spirit),
     LoadFilter(spirit),
     SubMemDataComposite_List(SubMemDataComposite_Arg,this)
  {
  }

  // Destructor
  virtual ~MemLoadFilter()
  {
  }

};

/*
** class MemStorage 叫用的
*/
class MemLoadFilterForPreserveLoad:public MemLoadFilter
{
  Smart_Ptr<cxxlList<MemLoadFilterForPreserveLoad> > SubLoadFilter_List; // 記錄要可被 toLoad() 叫用的子 MemLoadFilter
  cxxlPreserve *_pPreserve;

  bool OK;

public:
  MemLoadFilterForPreserveLoad(
    COMPOSITEMEMDATA *pMemDataComposite,
    cxxlPreserve *pPreserve,
    ISpirit *spirit )
    :cxxlObject(spirit),
     MemLoadFilter(pMemDataComposite->cxxlList_Create(),spirit),
     SubLoadFilter_List(new cxxlList<MemLoadFilterForPreserveLoad>(spirit),this)
  {
    isCommit = false;
    OK = true;
    _pPreserve = pPreserve;

    if(pPreserve == NULL)
    {
      if(pMemDataComposite->GetCount() != 0)
        OK = false;
      return;
    }

    Lock(pPreserve);

    if(GetTransaction(pPreserve) == 0)
    {
      SetTransaction(pPreserve,1);


      SubMemDataComposite_List->ResetPT(CxxlMan::toHead);

      for(const _Sets *p = Get_Sets_List(pPreserve);
          p != NULL;
          p = Next_Sets(p))
      {
        Smart_Ptr<COMPOSITEMEMDATA > SubMemDataComposite_Ptr = SubMemDataComposite_List->Pop_Front();

        if(SubMemDataComposite_Ptr->GetName() != SETCOUNT)
        {
          OK = false;
          break;
        }

        unsigned long SetCount; 
        Smart_Ptr<MemData> MemData_Ptr = SubMemDataComposite_Ptr->GetObj();
        SetCount = *(unsigned long*)MemData_Ptr->GetData();

        Smart_Ptr<cxxlList<cxxlPreserve> > cxxlPreserve_List = GetPreserveList(p);
        unsigned long SubPreserveCount = cxxlPreserve_List->GetCount();
        if(SetCount != SubPreserveCount)
        {
          OK = false;
          break;
        }

        if(SubPreserveCount == 0)
          continue;

        cxxlPreserve_List->ResetPT(toHead);
        unsigned long i = 0;
        for(Smart_Ptr<cxxlPreserve> cxxlPreserve_Ptr = (*cxxlPreserve_List)++; i < SubPreserveCount; cxxlPreserve_Ptr = (*cxxlPreserve_List)++, ++i)
        {
          MemLoadFilterForPreserveLoad *pMemLoadFilter = new MemLoadFilterForPreserveLoad(SubMemDataComposite_List->Pop_Front(), cxxlPreserve_Ptr, spirit);
          if(pMemLoadFilter->isOK() == false)
          {
            delete pMemLoadFilter;
            OK = false;
            return;
          }
          else
            SubLoadFilter_List->Push_Back(pMemLoadFilter);
        }

      }     
      
    }
  }

  virtual ~MemLoadFilterForPreserveLoad()
  {
    if(_pPreserve != NULL)
    {
      SetTransaction(_pPreserve,0);
      LoadFilter::UnLock(_pPreserve);
      _pPreserve = NULL;
    }
  }

  bool cxxlFASTCALL toLoad()
  {
    if(_pPreserve == NULL)
      return true;

    if(GetTransaction(_pPreserve) == 1)
    {
      SetTransaction(_pPreserve,2);

      SubMemDataComposite_List->ResetPT(CxxlMan::toHead);
      SubLoadFilter_List->ResetPT(CxxlMan::toHead);
      for(Smart_Ptr<MemLoadFilterForPreserveLoad> SubLoadFilter_Ptr = (*SubLoadFilter_List)++;
          !SubLoadFilter_Ptr.isNULL();
          SubLoadFilter_Ptr = (*SubLoadFilter_List)++)
      {
        if(SubLoadFilter_Ptr->toLoad() == false)
          return false;
      }

      return LoadFilter::Load(_pPreserve);
    }

    return true; // 共用元件已處理過
  }

  void cxxlFASTCALL toCommit(bool r)
  {
    if(_pPreserve == NULL)
      return;

    if(GetTransaction(_pPreserve) != 0)
    {
      if(GetTransaction(_pPreserve) == 2)
      {
        SetTransaction(_pPreserve, 0);

        SubLoadFilter_List->ResetPT(CxxlMan::toHead);
        SubMemDataComposite_List->ResetPT(CxxlMan::toHead);
        for(Smart_Ptr<MemLoadFilterForPreserveLoad> SubLoadFilter_Ptr = (*SubLoadFilter_List)++;
            !SubLoadFilter_Ptr.isNULL();
            SubLoadFilter_Ptr = (*SubLoadFilter_List)++)
        {
          SubLoadFilter_Ptr->toCommit(r);
        }

        isCommit = true;
        LoadFilter::Commit(_pPreserve,r);
      }
      else
        SetTransaction(_pPreserve, 0);

      LoadFilter::UnLock(_pPreserve);
      _pPreserve = NULL;
    }
  }

  bool cxxlFASTCALL isOK()
  {
    return OK;
  }

};

/*
** class Preserve2MemStorage 叫用的
*/
class MemLoadFilterForPreserve2Regenera:public MemLoadFilter
{
public:
  MemLoadFilterForPreserve2Regenera(
    const Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > &SubMemDataComposite_Arg,
    ISpirit *spirit )
    :cxxlObject(spirit),
     MemLoadFilter(SubMemDataComposite_Arg,spirit)
  {
  }

  virtual ~MemLoadFilterForPreserve2Regenera()
  {
  }

  bool cxxlFASTCALL toLoad(cxxlPreserve *pPreserve)
  {
    isCommit = false;
    SubMemDataComposite_List->ResetPT(CxxlMan::toHead);
    return LoadFilter::Load(pPreserve);
  }

  void cxxlFASTCALL toCommit(cxxlPreserve *pPreserve, bool r)
  {
    isCommit = true;
    SubMemDataComposite_List->ResetPT(CxxlMan::toHead);
    LoadFilter::Commit(pPreserve,r);
  }

};

/********************************
**  class Preserve2MemStorage
********************************/

class Preserve2MemStorage:public IPreserve2Storage
{
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > SubNode_List;
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Attr_List;

  UNICODE_String Name;
  UNICODE_String InterfaceID;
  UNICODE_String ClassID;
  UNICODE_String ObjID;
  UNICODE_String Group;
  UNICODE_String Spirit;

public:
  Preserve2MemStorage(
    const Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > &SubNode_Arg,
    const Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > &Attr_Arg,
    const UNICODE_String &Name_Arg,
    const UNICODE_String &InterfaceID_Arg,
    const UNICODE_String &ClassID_Arg,
    const UNICODE_String &ObjID_Arg,
    const UNICODE_String &Group_Arg,
    const UNICODE_String &Spirit_Arg,
    ISpirit *spirit)
    :cxxlObject(spirit),
     SubNode_List(SubNode_Arg),
     Attr_List(Attr_Arg),
     Name(Name_Arg),
     InterfaceID(InterfaceID_Arg),
     ClassID(ClassID_Arg),
     ObjID(ObjID_Arg),
     Group(Group_Arg),
     Spirit(Spirit_Arg)
  {
  }
  virtual ~Preserve2MemStorage()
  {

  }

  UNICODE_String cxxlFASTCALL GetName() const
  {
    return Name;
  }
  UNICODE_String cxxlFASTCALL GetInterfaceID() const
  {
    return InterfaceID;
  }
  UNICODE_String cxxlFASTCALL GetClassID() const
  {
    return ClassID;
  }
  UNICODE_String cxxlFASTCALL GetObjID() const
  {
    return ObjID;
  }
  UNICODE_String cxxlFASTCALL GetGroup() const
  {
    return Group;
  }
  UNICODE_String cxxlFASTCALL GetSpiritStr() const
  {
    return Spirit;
  }

  virtual bool isEmpty() const                         // 是空資料嗎(無子節點也無內容)
  {
    return SubNode_List->GetCount() == 0 && Attr_List->GetCount() == 0;
  }

  void ResetFirst() const                 // 重置子節點序列至第一個位置
  {
    SubNode_List->ResetPT(toHead);
  }

  bool haveSetCount() const               // 檢查還有沒有子節點子集
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubNode_Ptr = SubNode_List->GetObj();

    if(SubNode_Ptr.isNULL() || SubNode_Ptr->GetName() != SETCOUNT)
      return false;
    else
      return true;
  }

  unsigned long GetSetCount() const // 取得子節點子集數量
  {
    unsigned long SetCount;

    Smart_Ptr<COMPOSITEMEMDATA > SubNode_Ptr = (*SubNode_List)++;

    Smart_Ptr<MemData> MemData_Ptr = SubNode_Ptr->GetObj();

    SetCount = *(unsigned long*)MemData_Ptr->GetData();

    return SetCount;
  }

  Smart_Ptr<IPreserve2Storage> cxxlFASTCALL GetIPreserve2StorageFirst() const
  {
    SubNode_List->ResetPT(toHead);
    return GetIPreserve2StorageNext();
  }

  Smart_Ptr<IPreserve2Storage> cxxlFASTCALL GetIPreserve2StorageNext() const
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubNode_Ptr = (*SubNode_List)++;
    if(SubNode_Ptr.isNULL())
      return NULL;

    Smart_Ptr<CMem_attrComposite_Export> CMem_attrComposite_Export_Ptr = new CMem_attrComposite_Export;
    SubNode_Ptr->Export(CMem_attrComposite_Export_Ptr);

    return new Preserve2MemStorage(
                 CMem_attrComposite_Export_Ptr->GetSubNode_List(),
                 CMem_attrComposite_Export_Ptr->GetAttr_List(),
                 SubNode_Ptr->GetName(),
                 GetStr(SubNode_Ptr, INTERFACEIDNAME),
                 GetStr(SubNode_Ptr, CLASSIDNAME),
                 GetStr(SubNode_Ptr, OBJIDNAME),
                 GetStr(SubNode_Ptr, GROUPNAME),
                 GetStr(SubNode_Ptr, SPIRITNAME),
                 this->GetSpirit());
  }

  bool cxxlFASTCALL Load(const Smart_Ptr<cxxlPreserve> &v) const
  {
    MemLoadFilterForPreserve2Regenera LF(Attr_List,this->GetSpirit());
    bool r = LF.toLoad(v);
    LF.toCommit(v,r);
    return r;
  }

  static UNICODE_String cxxlFASTCALL GetStr(const Smart_Ptr<COMPOSITEMEMDATA > &Node_Ptr, const UNICODE_String &Name)
  {
    Smart_Ptr<MemData> MemData_Ptr = Node_Ptr->GetObj(Name);

    if(MemData_Ptr.isNULL())
      return UNICODE_String();

    if(MemData_Ptr->GetDataLen() == 0)
      return UNICODE_String();

    return (wchar_t *)MemData_Ptr->GetData();
  }

};



/********************************
** class MemStorage
********************************/

// Constructor
CxxlMan::MemStorage::MemStorage(ISpirit *spirit)
  :cxxlObject(spirit), Mem_Composite_Ptr(new Mem_attrComposite(L"root",spirit),this)
{
}

bool cxxlFASTCALL CxxlMan::MemStorage::toSave(cxxlPreserve *v,const UNICODE_String &Name)
{
  CriticalSecHandle AutoCSH(csObject);

  if(v == NULL || Mem_Composite_Ptr->GetComposite(Name).isNULL() == false)
    return false;

  Smart_Ptr<COMPOSITEMEMDATA > MemDataCompositeHost_Ptr = Mem_Composite_Ptr->Add(NULL, Name);
  if(MemDataCompositeHost_Ptr.isNULL())
    return false;

  MemSaveFilter SF(MemDataCompositeHost_Ptr, v, GetSpirit());

  if(SF.toSave())
    return true;

  Mem_Composite_Ptr->Delete(MemDataCompositeHost_Ptr);
  return false;
}

bool cxxlFASTCALL CxxlMan::MemStorage::toLoad(cxxlPreserve *v,const UNICODE_String &Name)
{
  CriticalSecHandle AutoCSH(csObject);

  if(v != NULL)
  {
    Smart_Ptr<COMPOSITEMEMDATA > MemDataCompositeHost_Ptr = Mem_Composite_Ptr->GetComposite(Name);
    if(MemDataCompositeHost_Ptr.isNULL() == false)
    {
      MemLoadFilterForPreserveLoad LF(MemDataCompositeHost_Ptr, v, GetSpirit());
      if(LF.isOK())
      {
        bool r = LF.toLoad();
        LF.toCommit(r);
        return r;
      }
    }
  }

  return false;
}


bool cxxlFASTCALL CxxlMan::MemStorage::Delete(const UNICODE_String &Name)
{
  return Mem_Composite_Ptr->Delete(Mem_Composite_Ptr->GetComposite(Name));
}

Smart_Ptr<IPreserve2Storage> cxxlFASTCALL CxxlMan::MemStorage::GetIPreserve2Storage(const UNICODE_String &Name)
{
  Smart_Ptr<COMPOSITEMEMDATA > MemDataCompositeHost_Ptr = Mem_Composite_Ptr->GetComposite(Name);
  if(MemDataCompositeHost_Ptr.isNULL())
    return NULL;

  Smart_Ptr<CMem_attrComposite_Export> CMem_attrComposite_Export_Ptr = new CMem_attrComposite_Export;
  MemDataCompositeHost_Ptr->Export(CMem_attrComposite_Export_Ptr);

  return new Preserve2MemStorage(
               CMem_attrComposite_Export_Ptr->GetSubNode_List(),
               CMem_attrComposite_Export_Ptr->GetAttr_List(),
               MemDataCompositeHost_Ptr->GetName(),
               Preserve2MemStorage::GetStr(MemDataCompositeHost_Ptr, INTERFACEIDNAME),
               Preserve2MemStorage::GetStr(MemDataCompositeHost_Ptr, CLASSIDNAME),
               Preserve2MemStorage::GetStr(MemDataCompositeHost_Ptr, OBJIDNAME),
               Preserve2MemStorage::GetStr(MemDataCompositeHost_Ptr, GROUPNAME),
               Preserve2MemStorage::GetStr(MemDataCompositeHost_Ptr, SPIRITNAME),
               this->GetSpirit());

}


/***********************************************************************/

class MemBuild
{
  std::ostream &os;
public:
  // Constructor
  MemBuild(std::ostream &out)
    :os(out)
  {
  }

  ~MemBuild() {}

  void cxxlFASTCALL NewNode(const UNICODE_String &Name_Ptr)
  {
    os.put('{');
    unsigned long Length = (Name_Ptr.StrLength() + 1) * sizeof(wchar_t);
    os.write( (const char*)(&Length), sizeof(Length));
    os.write( (const char*)((const wchar_t*)Name_Ptr), Length);
  }

  void cxxlFASTCALL NodeEnd()
  {
    os.put('}');
  }

  void cxxlFASTCALL NewIteam(const Smart_Ptr<COMPOSITEMEMDATA > &MemDataComposite_Ptr)
  {
    const UNICODE_String Name_Ptr = MemDataComposite_Ptr->GetName();
    os.put('-');
    unsigned long Length = (Name_Ptr.StrLength() + 1) * sizeof(wchar_t);
    os.write( (const char*)(&Length), sizeof(Length));
    os.write( (const char*)((const wchar_t*)Name_Ptr), Length);

    unsigned long DataLen;      // 記憶體資料陣列長度，以 byte 為單位
    const void *Data = MemDataComposite_Ptr->GetObj()->Get(DataLen);  // 記憶體資料陣列
    os.write( (const char*)(&DataLen), sizeof(DataLen));
    os.write( (const char*)(Data), DataLen);
  }
};

class MemDataCompositeReader
{

  MemBuild Builder;

public:
  // Constructor
  MemDataCompositeReader(std::ostream &out)
    :Builder(out)
  {
  }

  // Destructor
  ~MemDataCompositeReader()
  {
  }

  void cxxlFASTCALL cv(const Smart_Ptr<COMPOSITEMEMDATA > &MDC_Ptr)
  {
    Builder.NewNode(MDC_Ptr->GetName());

    Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > MDC_List =
      MDC_Ptr->cxxlList_Create();
    MDC_List->ResetPT(CxxlMan::toHead);
    unsigned long Count = MDC_List->GetCount();
    for(Smart_Ptr<COMPOSITEMEMDATA > p = (*MDC_List)++;
      Count > 0;
      p = (*MDC_List)++, --Count)
    {
      Smart_Ptr<MemData> MemData_Ptr = p->GetObj();
      if(MemData_Ptr.isNULL() == false)
        Builder.NewIteam(p);
      else
        cv(p);
    }

    Builder.NodeEnd();
  }
};


class BinaryListReader:virtual public cxxlObject
{
  std::istream &MDC_in;
public:
  // Constructor
  BinaryListReader(std::istream &in, ISpirit *spirit)
    :cxxlObject(spirit),MDC_in(in)
  {
  }

  // Destructor
  ~BinaryListReader()
  {
  }

  bool cxxlFASTCALL NewNode(const Smart_Ptr<COMPOSITEMEMDATA > &Parent_Ptr)
  {
    unsigned long NameLength;
    if(MDC_in.read((char *)(&NameLength),sizeof(NameLength)) == false)
      return false;
    UNICODE_String Name(NameLength / sizeof(wchar_t), this->GetSpirit());
    if(MDC_in.read((char *)((const wchar_t*)Name),NameLength) == false)
      return false;
    Smart_Ptr<COMPOSITEMEMDATA > Now = Parent_Ptr->Add(NULL,Name);


    while(true)
    {
      char tag;
      if(MDC_in.get(tag) == false)
        return false;
      switch(tag)
      {
      case '{':
        if(NewNode(Now) == false)
          return false;
        break;
      case '}':
        return true;
      case '-':
        {
          unsigned long NameLength;
          if(MDC_in.read((char*)(&NameLength),sizeof(NameLength)) == false)
            return false;
          UNICODE_String Name(NameLength / sizeof(wchar_t), this->GetSpirit());
          if(MDC_in.read((char *)((const wchar_t*)Name),NameLength) == false)
            return false;

          unsigned long DataLen;      // 記憶體資料陣列長度，以 byte 為單位
          if(MDC_in.read((char *)(&DataLen),sizeof(DataLen)) == false)
            return false;

          const void *Data = new char[DataLen];
          if(MDC_in.read((char*)Data,DataLen) == false)
            return false;

          MemData *pMemData = new MemData(DataLen,Data,this->GetSpirit());
          Now->Add(pMemData,Name);
        }
        break;
      default:
        return false;
      }
    }
  }

  Smart_Ptr<COMPOSITEMEMDATA > cxxlFASTCALL Start()
  {
    Smart_Ptr<COMPOSITEMEMDATA >
      Start_Ptr(new COMPOSITEMEMDATA(L"Start",GetSpirit()));

    char tag;
    if(MDC_in.get(tag) == false)
      return NULL;

    if(tag != '{')
      return NULL;

    if(NewNode(Start_Ptr) == false)
      return NULL;

    Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > MemComposite_List =
      Start_Ptr->cxxlList_Create();

    if(MemComposite_List->GetCount())
    {
      MemComposite_List->ResetPT(toHead);
      return MemComposite_List->GetObj();
    }
    else
      return NULL;
  }
};



CXXL_DLLEXPORT void cxxlFASTCALL
CxxlMan::MemStorageExportMDC(std::ostream &out, const Smart_Ptr<MemStorage> &MemStorage_Ptr)
{
  MemDataCompositeReader Reader(out);

  Reader.cv(MemStorage_Ptr->Mem_Composite_Ptr);

}

CXXL_DLLEXPORT Smart_Ptr<MemStorage> cxxlFASTCALL CxxlMan::MemStorageImportMDC(std::istream &MDC, ISpirit *spirit)
{
  BinaryListReader MDReader(MDC,spirit);

  Smart_Ptr<COMPOSITEMEMDATA > tmp_Ptr = MDReader.Start();
  if(tmp_Ptr.isNULL())
    return NULL;

  MemStorage *pMemStorage = new MemStorage(spirit);
  pMemStorage->Mem_Composite_Ptr = tmp_Ptr;

  return pMemStorage;
}


/************************************************************************************/

// 作為巡行記號
class Mark:public cxxlObject
{
  int Num; // 0 已退回，1 已進入， 2 重複進入
public:
  Mark()
    :cxxlObject(Spirit_Easy)
  {
    Num = 0;
  }

  int operator++()
  {
    return ++Num;
  }

  int operator--()
  {
    return --Num;
  }
};

// 以 preserve2 的 ObjID 為 Key 來記錄走過的次數
class ObjIDChk_Tree:public cxxlAVL_Tree<Mark, UNICODE_String, true>
{
  bool cxxlFASTCALL isLeftAt(UNICODE_String O_Key, UNICODE_String addKey) const
  {
    return O_Key <= addKey;
  }

  bool cxxlFASTCALL isEqual(UNICODE_String O_Key, UNICODE_String findKey)  const
  {
    return O_Key == findKey;
  } 

public:
  ObjIDChk_Tree()
    :cxxlObject(Spirit_Easy)
  {}
};

// 收集各技節點，若 ClearObjID 為 true，順便檢查是否有循環參照
bool cxxlFASTCALL Collect(const Smart_Ptr<COMPOSITEMEMDATA > &MemComposite_Arg, const Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > &Collect_Arg, const Smart_Ptr<ObjIDChk_Tree> &ObjIDChk_Arg, bool ClearObjID)
{  
  if(ClearObjID)
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubMemComposite_Ptr = MemComposite_Arg->GetComposite(OBJIDNAME);

    if(SubMemComposite_Ptr.isNULL() == false) // preserve2 的節點才須檢查
    {
      UNICODE_String Key = (wchar_t *)SubMemComposite_Ptr->GetObj()->GetData();
      ObjIDChk_Arg->Add(new Mark, Key);
      Smart_Ptr<Mark> Mark_Ptr = ObjIDChk_Arg->GetObj(Key);
      int Num = ++(*Mark_Ptr);
      if(Num == 2) // 走過了
        return false;
    }
  }

  Collect_Arg->Push_Back(MemComposite_Arg); // 把 preserve 或 preserve2 放入收集袋


  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Node_List = MemComposite_Arg->cxxlList_Create();

  Node_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITEMEMDATA > SubMemComposite_Ptr = (*Node_List)++;
    SubMemComposite_Ptr.isNULL() == false;
    SubMemComposite_Ptr = (*Node_List)++)
  {
    if(SubMemComposite_Ptr->GetObj().isNULL()) // 是技節點
      if(Collect(SubMemComposite_Ptr, Collect_Arg, ObjIDChk_Arg, ClearObjID) == false)
        return false;
  }

  if(ClearObjID)
  {
    Smart_Ptr<COMPOSITEMEMDATA > SubMemComposite_Ptr = MemComposite_Arg->GetComposite(OBJIDNAME);
    if(SubMemComposite_Ptr.isNULL() == false)
    {
      UNICODE_String Key = (wchar_t *)SubMemComposite_Ptr->GetObj()->GetData();
      Smart_Ptr<Mark> Mark_Ptr = ObjIDChk_Arg->GetObj(Key);
      --(*Mark_Ptr); // 退回
    }
  }

  return true;
}

// 負責把 preserve2 的 ObjID 資料清掉
void cxxlFASTCALL DoClearObjID(const Smart_Ptr<COMPOSITEMEMDATA > &COMPOSITEMEMDATA_Arg)
{
  Smart_Ptr<COMPOSITEMEMDATA > ObjIDNod_Ptr = COMPOSITEMEMDATA_Arg->GetComposite(OBJIDNAME);
  if(ObjIDNod_Ptr.isNULL())
    return;

  ObjIDNod_Ptr->GetObj()->SetDataLen(0);
}

// 負責把 preserve 的永存資料刪掉
void cxxlFASTCALL DoDelRestore(const Smart_Ptr<COMPOSITEMEMDATA > &COMPOSITEMEMDATA_Arg)
{
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Node_List = COMPOSITEMEMDATA_Arg->cxxlList_Create();

  Node_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITEMEMDATA > SubCOMPOSITEMEMDATA_Ptr = (*Node_List)++;
    SubCOMPOSITEMEMDATA_Ptr.isNULL() == false;
    SubCOMPOSITEMEMDATA_Ptr = (*Node_List)++)
  {
    if(SubCOMPOSITEMEMDATA_Ptr->GetObj().isNULL() == false)
    {
      // preserve2 的永存資料保留
      UNICODE_String Name = SubCOMPOSITEMEMDATA_Ptr->GetName(); 
      if(Name == SETCOUNT)
        continue;

      if(Name == INTERFACEIDNAME)
        continue;

      if(Name == CLASSIDNAME)
        continue;

      if(Name == OBJIDNAME)
        continue;

      if(Name == GROUPNAME)
        continue;

      if(Name == SPIRITNAME)
        continue;

      COMPOSITEMEMDATA_Arg->Delete(SubCOMPOSITEMEMDATA_Ptr);      
    }
  }
}

// 切斷 cxxlPreserve2 的永存資料中共用物件的資訊，即讓 ObjID 資訊失去作用
bool cxxlFASTCALL CutPreserve2(const Smart_Ptr<MemStorage> &MemStorage_Arg, bool ClearObjID, bool DelRestore)
{
  Smart_Ptr<COMPOSITEMEMDATA > MemComposite_Ptr = MemStorage_Arg->GetComposite();

  // 取得第一層所有物件永存資料的啟始節點
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Node_List = MemComposite_Ptr->cxxlList_Create();

  // 準備存放所有物件永存資料的 List
  Smart_Ptr<cxxlList<cxxlList<COMPOSITEMEMDATA > > > Collects_List = new cxxlList<cxxlList<COMPOSITEMEMDATA > >;

  Node_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITEMEMDATA > SubMemComposite_Ptr = (*Node_List)++;
    SubMemComposite_Ptr.isNULL() == false;
    SubMemComposite_Ptr = (*Node_List)++)
  {
    Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Collect_List = new cxxlList<COMPOSITEMEMDATA >;
    Smart_Ptr<ObjIDChk_Tree> ObjIDChk_Ptr = new ObjIDChk_Tree;
    if(Collect(SubMemComposite_Ptr, Collect_List, ObjIDChk_Ptr, ClearObjID) == false)
      return false;

    Collects_List->Push_Back(Collect_List);
  }

  Collects_List->ResetPT(toHead);
  for(Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Collect_List = (*Collects_List)++;
    Collect_List.isNULL() == false;
    Collect_List = (*Collects_List)++)
  {
    Collect_List->ResetPT(toHead);
    for(Smart_Ptr<COMPOSITEMEMDATA > COMPOSITEMEMDATA_Ptr = (*Collect_List)++;
      COMPOSITEMEMDATA_Ptr.isNULL() == false;
      COMPOSITEMEMDATA_Ptr = (*Collect_List)++)
    {
      if(ClearObjID)
        DoClearObjID(COMPOSITEMEMDATA_Ptr);

      if(DelRestore)
        DoDelRestore(COMPOSITEMEMDATA_Ptr);
    }    
  }

  return true;
}

// 切斷 cxxlPreserve2 的永存資料中共用物件的資訊，即讓 ObjID 資訊失去作用
bool cxxlFASTCALL CutPreserve2(const Smart_Ptr<MemStorage> &MemStorage_Arg, const UNICODE_String &Name, bool ClearObjID, bool DelRestore)
{
  Smart_Ptr<COMPOSITEMEMDATA > MemComposite_Ptr = MemStorage_Arg->GetComposite();

  // 只取指定名稱的物件永存資料的啟始節點
  Smart_Ptr<COMPOSITEMEMDATA > SubMemComposite_Ptr = MemComposite_Ptr->GetComposite(Name);

  if(SubMemComposite_Ptr.isNULL())
    return true; // 指定名稱的節點不存仍回覆 true

  // 準備存放指定物件永存資料節點的 List
  Smart_Ptr<cxxlList<COMPOSITEMEMDATA > > Collect_List = new cxxlList<COMPOSITEMEMDATA >;

  Smart_Ptr<ObjIDChk_Tree> ObjIDChk_Ptr = new ObjIDChk_Tree;
  if(Collect(SubMemComposite_Ptr, Collect_List, ObjIDChk_Ptr, ClearObjID) == false)
    return false;

  Collect_List->ResetPT(toHead);
  for(Smart_Ptr<COMPOSITEMEMDATA > COMPOSITEMEMDATA_Ptr = (*Collect_List)++;
    COMPOSITEMEMDATA_Ptr.isNULL() == false;
    COMPOSITEMEMDATA_Ptr = (*Collect_List)++)
  {
    if(ClearObjID)
      DoClearObjID(COMPOSITEMEMDATA_Ptr);

    if(DelRestore)
      DoDelRestore(COMPOSITEMEMDATA_Ptr);
  }    

  return true;    
}



